(function($, document, window) {

  var ns = jfPD,
      datePaused = null,
      $document = $(document);
  
  function init(e, config) {
    if (!$.mobile.path.stripHash(location.hash)) {
      window.setTimeout(function() {
        ns.controller.loadPage(ns.config.startUrl);
      }, 0);
    }
    
    document.addEventListener("backbutton", function() {
      if ($.mobile.urlHistory.activeIndex > 1) { //the first entry (index 0) is a blank page, the second entry (index 1) is the first 'real' page
        window.history.back();
      }
    }, false);
  }

  function onDeviceready() {
    isPhonegapApp = typeof window.PhoneGap !== 'undefined';

    ns.appType = 'native';
    
    if (isPhonegapApp) {

      if (window.navigator.notification) {
        //Override ns.alert method
        ns.alert = function(message, title, buttonName, alertCallback) {
          //original phonegap interface: navigator.notification.alert(message, alertCallback, [title], [buttonName])
          window.navigator.notification.alert(message, alertCallback, title, buttonName);
        };
      }
      

     if (window.ChildBrowser && window.ChildBrowser.install) {
       window.ChildBrowser.install(); //on iOS the ChildBrowser Plugin does not install itself automatically
     }
     
      /*
      if (window.debug) {
        ns.log = function(message) {
          window.debug.log(message);
        };
      }
      */
      
      document.addEventListener("pause", onPause, false);
      document.addEventListener("resume", onResume, false);
      document.addEventListener("offline", function() { ns.controller.onOnlineStateChange(false); }, false);
      document.addEventListener("online", function() { ns.controller.onOnlineStateChange(true); }, false);
      ns.controller.onOnlineStateChange(navigator.network.connection.type !== Connection.NONE);
      
    }
  }
  
  function onJfPDEnhancePage(e, $page) {
    $page.find('a[data-childbrowser]')
       .attr('data-ajax', false)
       .attr('target', '_self')
       .bind(ns.controller.clickEvent, onClickOpenChildbrowser);
  }
  
  function onPageShow(e) {
    hideBackButtonIfFirstPage($(this));
  }
  
  function hideBackButtonIfFirstPage($page) {
    var $button = $page.find('[data-rel=back]');
    if ($.mobile.urlHistory.activeIndex <= 1) {
      $button.hide();
    }
    else {
      $button.show();
    }
  }

  function onClickOpenChildbrowser(e) {
    var $link = $(this),
      url = $link.attr('href'),
      isSameDomain = ns.controller.isSameDomain(url);
  
    if (!window.plugins || !window.plugins.childBrowser) {
    
      if (!isSameDomain) {
        $link.attr('target', '_blank');
      }
    
      return;
    }
    

    e.stopPropagation();
    e.preventDefault();
    
    if (isSameDomain && $link.attr('data-childbrowser') !== 'true') {
      ns.controller.loadPage(url);
      //only enforce childbrowser for same fomain if data-childbrowser attribute is explicitly set to 'true'
      return;
    }

    if (!url.match(/^http/)) {
      return;
    }

    window.plugins.childBrowser.showWebPage(url);

    return false;
  }

  function onPause() {
    datePaused = new Date();
  }
  function onResume() {
    
    if (!ns.controller.getCurrentContainer()) {
      ns.controller.alert('App will be restarted', 'Unrecoverable error');
      ns.controller.reloadApp();
      return;
    }
    
    ns.controller.onOnlineStateChange(navigator.network.connection.type !== Connection.NONE);
    
    
    if (ns.config.refreshTimeout && ns.config.refreshTimeout > 0 && datePaused) {
      var currentDate = new Date();
      if ((currentDate.getTime() - datePaused.getTime())/1000 > ns.config.refreshTimeout) {
        ns.controller.refreshPages();
      }
    }
    datePaused = null;
  }
  
  $.support.cors = true;
  $.ajaxSetup({
    headers: {'X-Requested-With': 'XMLHttpRequest' }, //sometimes X-REQUESTED-WITH header is missing and thus some frameworks (e.g. Symfony) won't recognized that the request is an XHR request
    crossDomain: true
  }); 
  $.mobile.allowCrossDomainPages = true;
  $.mobile.pushStateEnabled = false; //pushing state currently results in SECURITY_ERR: Dom Exception 18 on android devices

  $document.bind('jfPD:init', init); //event must be bound using jQuery ($)!
  $document.bind('jfPD:enhancePage', onJfPDEnhancePage);
  $("div:jqmData(role='page')").live('pageshow', onPageShow);
  document.addEventListener("deviceready", onDeviceready, false); //event must not be bound using jQuery but using document.addEventListener!
  
})(jQuery, document, window);